using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using ALib;
using ALib.Data.IO;
using ALib.Misc;

namespace TradingPlatform
{
    public partial class TradingGui : TradingGuiBase
    {
        private readonly Timer _tradingStatusAndStatusBarUpdateTimer;

        private readonly TradingKernel _tradingKernel;

        public TradingGui(TradingKernel tradingKernel)
        {
            InitializeComponent();

            _tradingKernel = tradingKernel;
            TradingStatus_Init();

            _tradingKernel.OnDisplayStatus += new TradingKernel.TradingGuiDisplayEventHandler(_tradingKernel_OnDisplayStatus);
            _tradingKernel.OnDisplayOmsOrders += new TradingKernel.TradingGuiDisplayEventHandler(_tradingKernel_OnDisplayOmsOrders);
            _tradingKernel.OnDisplayOmsOpenPosition += new TradingKernel.TradingGuiDisplayEventHandler(_tradingKernel_OnDisplayOmsOpenPosition);
            _tradingKernel.OnDisplayErrorMessage += new TradingKernel.TradingGuiDisplayEventHandler(_tradingKernel_OnDisplayErrorMessage);

            _tradingStatusAndStatusBarUpdateTimer = new Timer();
            _tradingStatusAndStatusBarUpdateTimer.Interval = 500;
            _tradingStatusAndStatusBarUpdateTimer.Tick += new EventHandler(_tradingStatusAndStatusBarUpdateTimer_Tick);
            _tradingStatusAndStatusBarUpdateTimer.Enabled = true;
            _tradingStatusAndStatusBarUpdateTimer.Start();

            Configuration configuration = new Configuration(@"Configuration\ConnectionToStrategy.txt");
            string strategyIp = configuration.GetString(KeyWordStrategyConnection.StrategyServerIp);
            string strategyPort = configuration.GetString(KeyWordStrategyConnection.StrategyServerPort);

            string trdingClientName = _tradingKernel != null ? _tradingKernel.TradingClientName : string.Empty;
            Text = string.Format(@"TradingClient:{0}@{1}@{2}:{3}", _tradingKernel.TradingKernelDescription, strategyIp, strategyPort, trdingClientName);
            ObjectTuple3<int, int, string> tradingTiming = _tradingKernel.TradingTimingList[0];
            tradingProgressBar.Config("", tradingTiming.Object0, tradingTiming.Object1, tradingTiming.Object2, 1000);

            _tradingKernel.TradingComm.setGui(this);

            if (_tradingKernel.StartTrading)
            {
                buttonConnectStrategy.Enabled = false;
                buttonPreloadData.Enabled = false;
                buttonConnectTradingApi.Enabled = false;
                buttonStartTrading.Enabled = false;

                Timer startTradingAllInOne = new Timer();
                startTradingAllInOne.Interval = 1000;
                startTradingAllInOne.Tick += new EventHandler(startTradingAllInOne_Tick);
                startTradingAllInOne.Enabled = true;
            }
        }

        void startTradingAllInOne_Tick(object sender, EventArgs e)
        {
            ((Timer)sender).Stop();
            _tradingKernel.StartTradingAllInOne();
        }

        private void buttonConnectStrategy_Click(object sender, EventArgs e)
        {
            _tradingKernel.ConnectStrategy();
        }

        private void buttonPreloadData_Click(object sender, EventArgs e)
        {
            _tradingKernel.PreloadData();
        }

        private void buttonConnectTradingApi_Click(object sender, EventArgs e)
        {
            _tradingKernel.ConnectTradingApi();
        }

        private void buttonStartTrading_Click(object sender, EventArgs e)
        {
            _tradingKernel.StartTimerBasedTrading();
        }

        private void TradingStatus_Init()
        {
            tradingStatus.BeginUpdate();
            TickerInfoDb tickerInfoDb = _tradingKernel.TickerInfoDb;
            foreach (string tickerName in tickerInfoDb.TickerNameList)
            {
                string pointValue = tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.strategyPointValue);
                string minMove = tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.strategyMinMove);
                string lotSize = tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.strategyLotSize);
                tradingStatus.UpdateValue(tickerName, TradingStatusItemType.PointValue, pointValue);
                tradingStatus.UpdateValue(tickerName, TradingStatusItemType.MinMove, minMove);
                tradingStatus.UpdateValue(tickerName, TradingStatusItemType.LotSize, lotSize);
            }
            tradingStatus.EndUpdate();
        }

        void _tradingStatusAndStatusBarUpdateTimer_Tick(object sender, EventArgs e)
        {
            tradingStatus.BeginUpdate();
            TradingStatus_UpdateTickData();
            TradingStatus_UpdateOpenPosition();
            tradingStatus.EndUpdate();

            StatusBar_UpdateOpenPosition();
        }

        private void TradingStatus_UpdateTickData()
        {
            SortedList<string, double[]> lastTicks = _tradingKernel.LastTicks;
            if (lastTicks != null)
            {
                SortedList<string, double[]> ticks = lastTicks;

                foreach (KeyValuePair<string, double[]> tickerName_Tick in ticks)
                {
                    tradingStatus.UpdateValue(tickerName_Tick.Key, TradingStatusItemType.BidVolume, tickerName_Tick.Value[0].ToString());
                    tradingStatus.UpdateValue(tickerName_Tick.Key, TradingStatusItemType.Bid, tickerName_Tick.Value[1].ToString());
                    tradingStatus.UpdateValue(tickerName_Tick.Key, TradingStatusItemType.Ask, tickerName_Tick.Value[2].ToString());
                    tradingStatus.UpdateValue(tickerName_Tick.Key, TradingStatusItemType.AskVolume, tickerName_Tick.Value[3].ToString());
                    tradingStatus.UpdateValue(tickerName_Tick.Key, TradingStatusItemType.Price, tickerName_Tick.Value[4].ToString());
                    tradingStatus.UpdateValue(tickerName_Tick.Key, TradingStatusItemType.Volume, tickerName_Tick.Value[5].ToString());
                    tradingStatus.UpdateValue(tickerName_Tick.Key, TradingStatusItemType.TotalVolume, tickerName_Tick.Value[6].ToString());
                }
            }
        }

        private void TradingStatus_UpdateOpenPosition()
        {
            tradingStatus.BeginUpdate();

            TickerInfoDb tickerInfoDb = _tradingKernel.TickerInfoDb;
            OrderManagementDb orderManagementDb = _tradingKernel.OrderManagementDb;

            Dictionary<string, double> openPositionList = orderManagementDb != null ? orderManagementDb.OpenPositionList : new Dictionary<string, double>();

            foreach (string tickerName in tickerInfoDb.TickerNameList)
            {
                double openPosition = openPositionList.ContainsKey(tickerName) ? openPositionList[tickerName] : 0;
                tradingStatus.UpdateValue(tickerName, TradingStatusItemType.OpenPosition, openPosition.ToString());
            }
            tradingStatus.EndUpdate();
        }

        private void StatusBar_UpdateOpenPosition()
        {
            OrderManagementDb orderManagementDb = _tradingKernel.OrderManagementDb;

            Dictionary<string, double> openPositionList = orderManagementDb != null ? orderManagementDb.OpenPositionList : new Dictionary<string, double>();

            // Update the status bar.
            List<double> openPositions = new List<double>();

            foreach (KeyValuePair<string, double> tickerName_OpenPosition in openPositionList)
            {
                if (tickerName_OpenPosition.Value != 0)
                {
                    openPositions.Add(tickerName_OpenPosition.Value);
                }
            }
            if (openPositions.Count==0)
            {
                openPositions.Add(0);
            }

            string openPositionString = CollectionToString.ListToString(openPositions, ",");
            toolStripStatusLabelOpenPositionValue.Text = string.Format(openPositionString);
            if (openPositionString == "0")
            {
                toolStripStatusLabelOpenPositionValue.ForeColor = SystemColors.ControlText;
                toolStripStatusLabelOpenPositionValue.BackColor = SystemColors.Control;

            }
            else
            {
                toolStripStatusLabelOpenPositionValue.ForeColor = Color.White;
                toolStripStatusLabelOpenPositionValue.BackColor = Color.Green;
            }
        }

        protected void DisplayStatus(string outputString)
        {
            listBoxStatus.BeginUpdate();
            bool selectedLastItem = listBoxStatus.SelectedIndex == listBoxStatus.Items.Count - 1;
            listBoxStatus.Items.Add(DateTime.Now.ToString(DateTimeFormatType.Complete) + "\t" + outputString + "(" + System.Threading.Thread.CurrentThread.ManagedThreadId + ")");
            if (listBoxStatus.Items.Count > 1000)
            {
                listBoxStatus.Items.RemoveAt(0);
            }
            if (selectedLastItem)
            {
                listBoxStatus.SetSelected(listBoxStatus.Items.Count - 1, true);
            }
            listBoxStatus.EndUpdate();
        }

        protected void DisplayOrderManagementOrders(string orderString)
        {
            textBoxOrderManagementOrders.Text = orderString;
        }

        protected void DisplayOrderManagementOpenPosition(string orderString)
        {
            textBoxOrderManagementOpenPosition.Text = orderString;
        }

        protected void DisplayErrorMessage(string outputString)
        {
            listBoxErrorMessage.BeginUpdate();
            bool selectedLastItem = listBoxErrorMessage.SelectedIndex == listBoxErrorMessage.Items.Count - 1;
            listBoxErrorMessage.Items.Add(DateTime.Now.ToString(DateTimeFormatType.Complete) + "\t" + outputString);
            if (listBoxErrorMessage.Items.Count > 1000)
            {
                listBoxErrorMessage.Items.RemoveAt(0);
            }
            if (selectedLastItem)
            {
                listBoxErrorMessage.SetSelected(listBoxErrorMessage.Items.Count - 1, true);
            }
            listBoxErrorMessage.EndUpdate();
        }

        void _tradingKernel_OnDisplayStatus(string outputString)
        {
            DisplayStatus(outputString);
        }

        void _tradingKernel_OnDisplayOmsOrders(string outputString)
        {
            DisplayOrderManagementOrders(outputString);
        }

        void _tradingKernel_OnDisplayOmsOpenPosition(string outputString)
        {
            DisplayOrderManagementOpenPosition(outputString);
        }

        void _tradingKernel_OnDisplayErrorMessage(string outputString)
        {
            DisplayErrorMessage(outputString);
        }

        private void buttonClearOpenPositioin_Click(object sender, EventArgs e)
        {
            DialogResult dialogResult = MessageBox.Show("All open position will be set to 0, and all Oms orders will cleared.\r\nYou must manually keep the open position and order consistancy with the broker trading system.", "Warning: Reset Open Position", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
            if (dialogResult == DialogResult.OK)
            {
                _tradingKernel.OrderManagementDb.FlatOpenPosition();
                _tradingKernel.OrderManagementDb.CancelAllOrders();
            }
        }

        /******************************************************
        * Connection state change call back
        ******************************************************/
        protected override void CommConnectedHandle(string str)
        {
            DisplayStatus(str);
            _tradingKernel.LoginApi();
        }

        protected override void CommDisconnectedHandle(string str)
        {
            DisplayStatus(str);
        }

        protected override void CommDataReadHandle(List<CommMessage> msgList)
        {
            for (int i = 0; i < msgList.Count; ++i)
            {
                CommMessage msg = msgList[i];
                if (LoginStatusMessage.Type.Equals(msg.TypeField.Value))
                {
                    LoginStatusMessage login = (LoginStatusMessage)msg;
                    if (login.Login())
                    {
                        DisplayStatus("Login comm successfully");
                        Random rnd = new Random();
                        _tradingKernel.TradingComm.InsertOrder(rnd.Next(1, 100), "DLa", 2300, 1, CommOrderTypeField.Type.Lmt);
                    }
                }
                else if (MarketDataBestLevelMessage.Type.Equals(msg.TypeField.Value))
                {
                    _tradingKernel.UpdateMarketBidAsk((MarketDataBestLevelMessage)msg);
                }
                else if (MarketDataTradeMessage.Type.Equals(msg.TypeField.Value))
                {
                    _tradingKernel.UpdateMarketTraded((MarketDataTradeMessage)msg);
                }
                else if (OrderStatusMessage.Type.Equals(msg.TypeField.Value))
                {
                    //_tradingKernel.UpdateOrderStatus((OrderStatusMessage)msg);
                    //DisplayStatus(msg.ToPlainText());
                }
                else
                {
                    DisplayStatus(msg.ToPlainText());
                }

            }
        }

        public override void DisplayMessage(string str)
        {
            DisplayStatus(str);
        }
    }
}